package net.cyan.arachne;

import net.cyan.arachne.urlrewrite.*;

import java.util.List;

/**
 * @author camel
 * @date 2008-7-31
 */
public class DefaultUrlMapper implements UrlMapper
{
    public static final DefaultUrlMapper INSTANCE = new DefaultUrlMapper();

    private DefaultUrlMapper()
    {
    }

    public void map(URLPattern pattern, PageMethod method, PageClass pageClass)
    {
        StringBuilder form = new StringBuilder();
        StringBuilder query = null;

        String to = null;
        String methodName = null;
        List<URLPattern.Item> paths = pattern.getPaths();
        int n = paths.size();
        for (int i = 0; i < n; i++)
        {
            URLPattern.Item path = paths.get(i);
            if (i > 0)
                form.append("/");
            if (path.isVariable())
            {
                String content = path.getContent();
                if (content.equals("@class"))
                {
                    form.append(".+");
                    to = "$u(" + i + "," + (i - n) + ")";
                }
                else if (content.equals("@method"))
                {
                    form.append("[^/]+");
                    methodName = "$u(" + i + ")";
                }
                else
                {
                    form.append("[^/]+");
                    if (query == null)
                        query = new StringBuilder();
                    else
                        query.append("&");
                    query.append(content).append("=$u(").append(i).append(")");
                }
            }
            else
            {
                form.append(path.getContent());
            }
        }

        URLPattern.Item postfix = pattern.getPostfix();
        if (postfix != null)
        {
            String content = postfix.getContent();
            if (postfix.isVariable())
            {
                if (content.equals("@class"))
                {
                    form.append("\\..+");
                    to = "$e()";
                }
                else if (content.equals("@method"))
                {
                    form.append("\\.[^/]+");
                    methodName = "$e()";
                }
                else
                {
                    form.append("\\.[^/]+");
                    if (query == null)
                        query = new StringBuilder();
                    else
                        query.append("&");
                    query.append(content).append("=$e()");
                }
            }
            else
            {
                form.append("\\.").append(content);
            }
        }

        for (URLPattern.Parameter parameter : pattern.getParameters())
        {
            String variable = parameter.getVariable();
            String name = parameter.getName();
            if (variable.equals("@class"))
            {
                to = "$p(" + name + ")";
            }
            else if (variable.equals("@method"))
            {
                methodName = "$p(" + name + ")";
            }
            else
            {
                if (query == null)
                    query = new StringBuilder();
                else
                    query.append("&");
                query.append(variable).append("=$p(").append(name).append(")");
            }
        }

        if (to == null)
            to = pageClass.getUrl();
        to += PageConfig.URIPLIT + (method == null ? methodName : method.getName()) + "." +
                (method == null ? PageConfig.getPostfix() : method.getPostfix());
        if (query != null)
            to += "?" + query;

        UrlRewriteFilter.addRewriter(new RegUrlRewriter(form.toString(), to, false));
    }
}
